<?php
/**
 * Soar Framework - Lightweight and simple to use PHP Framework
 *
 * Soar is free software and is distributed WITHOUT ANY WARRANTY
 *
 * @package Soar
 * @version 1.0 $Id: Soar.php 2 2012-04-06 21:50:33Z shay@shayanderson.com $
 * @copyright Copyright (c) 2012 ShayAnderson.com
 * @license http://www.gnu.org/licenses/gpl.html GPL License
 * @link http://www.shayanderson.com/projects/soar-php-framework.htm
 */

/**
 * Soar Framework Class
 *
 * @package Soar
 * @name Soar
 * @author Shay Anderson 03.12
 */
final class Soar
{
	/**
	 * Request error types
	 */
	const ERROR_404 = 0;
	const ERROR_500 = 1;

	/**
	 * Controller object
	 *
	 * @var SoarController
	 */
	private static $__controller;

	/**
	 * Run flag
	 *
	 * @var bool
	 */
	private static $__is_running = false;

	/**
	 * Registry object
	 *
	 * @var SoarRegistry
	 */
	private static $__registry;

	/**
	 * View object
	 *
	 * @var SoarView
	 */
	private static $__view;

	/**
	 * Add config file
	 *
	 * @param string $conf_path
	 * @return void
	 */
	public static function confFile($conf_path)
	{
		SoarConf::file($conf_path);
	}

	/**
	 * Finalize framework method
	 *
	 * @return void
	 */
	public static function finalize()
	{
		if(self::$__controller !== NULL)
		{
			self::$__controller->finalize();
		}
		self::log(__CLASS__ . ': finalized', SoarDebugger::LEVEL_DEBUG);
		SoarDebugger::writeLog();
	}

	/**
	 * Log message
	 *
	 * @param string $log_message
	 * @param int $level
	 * @return void
	 */
	public static function log($log_message, $level = SoarDebugger::LEVEL_ALL)
	{
		SoarDebugger::log($log_message, $level);
	}

	/**
	 * Run Soar Framework
	 *
	 * @return void
	 */
	public static function run()
	{
		if(!self::$__is_running)
		{
			self::$__is_running = true;

			// init params
			$conf = &SoarConf::getInstance();
			$router = &SoarRouter::getInstance();

			// init View if no view set
			if(empty(self::$__view))
			{
				SoarTemplateEngine::$file_ext = $conf->core->file->ext_template;
				SoarTemplateEngine::$template_dir = $conf->core->dir->tpl;
				self::$__view = new View(new SoarTemplateEngine);
			}

			// init Registry if not set
			if(empty(self::$__registry))
			{
				self::$__registry = new SoarRegistry();
			}

			// init module
			if(!is_dir($router->getModuleDir()))
			{
				if($conf->core->router->controller_require)
				{
					if($conf->core->debug)
					{
						trigger_error("Failed to run application, cannot find module directory \"{$router->getModuleDir()}\"",
							SoarErrorHandler::ERROR);
					}
					else
					{
						self::runError(self::ERROR_404);
					}
				}
			}
			else
			{
				// init controller
				self::log(__CLASS__ . ': Module "' . $router->getModuleDir() . '" initialized', SoarDebugger::LEVEL_DEBUG);
				$controller_name = $router->getControllerName();
				if(!is_file($router->getControllerPath()))
				{
					if($conf->core->router->controller_require)
					{
						if($conf->core->debug)
						{
							trigger_error("Failed to run application, cannot find controller file \"{$router->getControllerPath()}\"",
								SoarErrorHandler::ERROR);
						}
						else
						{
							self::runError(self::ERROR_404);
						}
					}
				}
				else
				{
					self::log(__CLASS__ . ': Controller file "' . $router->getControllerPath() . '" initialized',
						SoarDebugger::LEVEL_DEBUG);
					if(!class_exists($router->getControllerName()))
					{
						if($conf->core->router->controller_require)
						{
							if($conf->core->debug)
							{
								trigger_error("Failed to run application, cannot find controller \"{$controller_name}\"",
									SoarErrorHandler::ERROR);
							}
							else
							{
								self::runError(self::ERROR_404);
							}
						}
					}
					else
					{
						self::log(__CLASS__ . ': ' . $controller_name . ' initialized', SoarDebugger::LEVEL_DEBUG);
						self::$__controller = new $controller_name(self::$__view, self::$__registry);
						if(!self::$__controller instanceof SoarController)
						{
							trigger_error("Failed to run application, controller \"{$controller_name}\" (\"{$router->getControllerPath()}\")"
								. ' must be a child class of "SoarController" (or a child class of "Controller" which must be child'
								. ' class of "SoarController")', SoarErrorHandler::ERROR);
						}

						// call action
						if(!method_exists(self::$__controller, $router->getActionName()))
						{
							if($conf->core->router->controller_require)
							{
								if($conf->core->debug)
								{
									trigger_error("Failed to run application, action \"{$router->getActionName()}\" (method) for controller "
										. "\"{$controller_name}\" (\"{$router->getControllerPath()}\") does not exist", SoarErrorHandler::ERROR);
								}
								else
								{
									self::runError(self::ERROR_404);
								}
							}
						}
						else
						{
							self::$__controller->{$router->getActionName()}();
							self::log(__CLASS__ . ': ' . $controller_name . '->' . $router->getActionName() . '(): initialized',
								SoarDebugger::LEVEL_DEBUG);
						}
					}
				}
			}

			// auto display template file
			if($conf->core->router->template_auto_display && !self::$__view->isDisplayed())
			{
				if(!is_file($router->getTemplatePath()))
				{
					trigger_error("Failed to run application, cannot find template file \""
						. $router->getTemplatePath() . '"', SoarErrorHandler::ERROR);
				}
				self::log(__CLASS__ . ': Template file "' . $router->getTemplatePath() . '" initialized',
					SoarDebugger::LEVEL_DEBUG);
				self::$__view->display($router->getTemplatePath(false));
				self::log(__CLASS__ . ': Template file output', SoarDebugger::LEVEL_DEBUG);
			}

			// finalize
			self::finalize();
		}
	}

	/**
	 * Handle run errors
	 *
	 * @return void
	 */
	public static function runError($type)
	{
		switch((int)$type)
		{
			case self::ERROR_404:
				self::$__controller = new Error404Controller(self::$__view, self::$__registry);
				break;
			case self::ERROR_500:
				self::$__controller = new Error500Controller(self::$__view, self::$__registry);
				break;
		}
		if(self::$__controller !== NULL)
		{
			self::$__controller->action();
		}
	}

	/**
	 * Registry object setter
	 *
	 * @param SoarRegistry $registry
	 * @return void
	 */
	public static function setRegistry(SoarRegistry &$registry)
	{
		self::$__registry = &$registry;
	}

	/**
	 * View object setter
	 *
	 * @param SoarView $view
	 * @return void
	 */
	public static function setView(SoarView &$view)
	{
		self::$__view = &$view;
	}
}
?>